import uuid
from datetime import datetime
from flask import request, jsonify, current_app
from sqlalchemy import and_, or_
from flasgger import swag_from
from app import db
from app.models.user import User
from app.models.venue import Venue, VenueTimeSlot
from app.models.order import Order
from app.api.v1 import api_v1
from app.utils.decorators import login_required
from app.utils.order import generate_order_no, generate_checkin_code
from app.api.v1.docs.order_docs import (
    CREATE_ORDER_DOC, GET_ORDER_DETAIL_DOC, GET_USER_ORDERS_DOC,
    CANCEL_ORDER_DOC, CHECKIN_ORDER_DOC
)

@api_v1.route('/orders', methods=['POST'])
@swag_from(CREATE_ORDER_DOC)
@login_required
def create_order():
    """创建预约订单"""
    data = request.get_json()
    if not data:
        return jsonify({'code': 400, 'message': '缺少请求数据'}), 400
    
    # 验证必要参数
    required_fields = ['userId', 'venueId', 'timeSlotId', 'reservationDate']
    for field in required_fields:
        if field not in data:
            return jsonify({'code': 400, 'message': f'缺少必要参数: {field}'}), 400
    
    user_id = data.get('userId')
    venue_id = data.get('venueId')
    time_slot_id = data.get('timeSlotId')
    reservation_date_str = data.get('reservationDate')
    participant_count = data.get('participantCount', 1)
    remark = data.get('remark', '')
    
    # 验证用户
    user = User.query.get(user_id)
    if not user:
        return jsonify({'code': 404, 'message': '用户不存在'}), 404
    
    # 验证场馆
    venue = Venue.query.get(venue_id)
    if not venue:
        return jsonify({'code': 404, 'message': '场馆不存在'}), 404
    if venue.status != 1:
        return jsonify({'code': 403, 'message': '该场馆暂未开放'}), 403
    
    # 验证时间段
    time_slot = VenueTimeSlot.query.get(time_slot_id)
    if not time_slot:
        return jsonify({'code': 404, 'message': '时间段不存在'}), 404
    if time_slot.status != 1:
        return jsonify({'code': 403, 'message': '该时间段暂未开放'}), 403
    if time_slot.venue_id != venue_id:
        return jsonify({'code': 400, 'message': '时间段与场馆不匹配'}), 400
    
    # 解析预约日期
    try:
        reservation_date = datetime.strptime(reservation_date_str, '%Y-%m-%d').date()
    except ValueError:
        return jsonify({'code': 400, 'message': '日期格式错误，请使用YYYY-MM-DD格式'}), 400
    
    # 验证日期是否合法（不能是过去的日期） - 使用北京时间
    from datetime import timezone, timedelta
    beijing_tz = timezone(timedelta(hours=8))
    beijing_now = datetime.now(beijing_tz)
    today = beijing_now.date()
    if reservation_date < today:
        return jsonify({'code': 400, 'message': '不能预约过去的日期'}), 400
    
    # 验证日期对应的星期几是否与时间段匹配
    day_of_week = reservation_date.isoweekday()  # 1-7 代表周一到周日
    if time_slot.day_of_week != day_of_week:
        return jsonify({'code': 400, 'message': '所选时间段在该日期不可用'}), 400
    
    # 检查该时间段是否已满（按人数计算）
    existing_orders = Order.query.filter(
        Order.venue_id == venue_id,
        Order.time_slot_id == time_slot_id,
        Order.reservation_date == reservation_date,
        Order.status.in_([0, 1, 3])  # 未支付、已支付、已完成的订单
    ).all()
    
    existing_participants = sum(order.participant_count or 1 for order in existing_orders)
    remaining_capacity = time_slot.capacity - existing_participants
    
    if participant_count > remaining_capacity:
        return jsonify({'code': 400, 'message': f'该时间段剩余容量不足，剩余{remaining_capacity}人，您要预约{participant_count}人'}), 400
    
    # 检查用户是否已经预约了同一时间段
    user_existing_order = Order.query.filter(
        Order.user_id == user_id,
        Order.venue_id == venue_id,
        Order.time_slot_id == time_slot_id,
        Order.reservation_date == reservation_date,
        Order.status.in_([0, 1])  # 未支付、已支付的订单
    ).first()
    
    if user_existing_order:
        return jsonify({'code': 400, 'message': '您已预约该时间段'}), 400
    
    # 创建订单
    try:
        order = Order(
            order_no=generate_order_no(),
            user_id=user_id,
            venue_id=venue_id,
            time_slot_id=time_slot_id,
            reservation_date=reservation_date,
            start_time=time_slot.start_time,
            end_time=time_slot.end_time,
            amount=time_slot.price * participant_count,  # 按人数计算总金额
            participant_count=participant_count,
            status=0,  # 未支付
            remark=remark
        )
        
        db.session.add(order)
        db.session.commit()
        
        return jsonify({
            'code': 200,
            'message': '订单创建成功',
            'data': {
                'orderId': order.id,
                'orderNo': order.order_no,
                'orderInfo': order.to_dict()
            }
        })
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"创建订单异常: {str(e)}")
        return jsonify({'code': 500, 'message': '服务器错误'}), 500


@api_v1.route('/orders/<int:order_id>', methods=['GET'])
@swag_from(GET_ORDER_DETAIL_DOC)
@login_required
def get_order_detail(order_id):
    """获取订单详情"""
    user_id = request.args.get('userId')
    
    order = Order.query.get_or_404(order_id)
    
    # 验证订单所属用户
    if str(order.user_id) != str(user_id):
        return jsonify({'code': 403, 'message': '无权访问该订单'}), 403
    
    return jsonify({
        'code': 200,
        'message': '获取成功',
        'data': order.to_dict(with_venue=True)
    })


@api_v1.route('/user/<int:user_id>/orders', methods=['GET'])
@swag_from(GET_USER_ORDERS_DOC)
@login_required
def get_user_orders(user_id):
    """获取用户订单列表"""
    # 获取查询参数
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('perPage', 10, type=int)
    status = request.args.get('status')
    
    # 构建查询
    query = Order.query.filter_by(user_id=user_id)
    
    # 按状态筛选
    if status is not None:
        try:
            status_int = int(status)
            query = query.filter_by(status=status_int)
        except ValueError:
            pass
    
    # 分页查询
    pagination = query.order_by(Order.created_at.desc()).paginate(page=page, per_page=per_page)
    orders = pagination.items
    
    # 构建响应
    return jsonify({
        'code': 200,
        'message': '获取成功',
        'data': {
            'total': pagination.total,
            'pages': pagination.pages,
            'page': page,
            'perPage': per_page,
            'orders': [order.to_dict(with_venue=True) for order in orders]
        }
    })


@api_v1.route('/orders/<int:order_id>/cancel', methods=['POST'])
@swag_from(CANCEL_ORDER_DOC)
@login_required
def cancel_order(order_id):
    """取消订单"""
    data = request.get_json()
    if not data:
        return jsonify({'code': 400, 'message': '缺少请求数据'}), 400
    
    user_id = data.get('userId')
    
    order = Order.query.get_or_404(order_id)
    
    # 验证订单所属用户
    if str(order.user_id) != str(user_id):
        return jsonify({'code': 403, 'message': '无权操作该订单'}), 403
    
    # 验证订单状态
    if order.status not in [0]:  # 只有未支付的订单可以取消
        return jsonify({'code': 400, 'message': '该订单状态不允许取消'}), 400
    
    try:
        order.status = 2  # 已取消
        db.session.commit()
        
        return jsonify({
            'code': 200,
            'message': '订单取消成功',
            'data': order.to_dict()
        })
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"取消订单异常: {str(e)}")
        return jsonify({'code': 500, 'message': '服务器错误'}), 500


@api_v1.route('/orders/<int:order_id>/checkin', methods=['POST'])
@swag_from(CHECKIN_ORDER_DOC)
@login_required
def checkin_order(order_id):
    """订单签到"""
    data = request.get_json()
    if not data:
        return jsonify({'code': 400, 'message': '缺少请求数据'}), 400
    
    user_id = data.get('userId')
    checkin_code = data.get('checkinCode')
    
    if not checkin_code:
        return jsonify({'code': 400, 'message': '缺少签到码'}), 400
    
    order = Order.query.filter_by(id=order_id, checkin_code=checkin_code).first()
    if not order:
        return jsonify({'code': 404, 'message': '订单不存在或签到码错误'}), 404
    
    # 验证订单所属用户
    if str(order.user_id) != str(user_id):
        return jsonify({'code': 403, 'message': '无权操作该订单'}), 403
    
    # 验证订单状态
    if order.status != 1:  # 只有已支付的订单可以签到
        return jsonify({'code': 400, 'message': '该订单状态不允许签到'}), 400
    
    # 验证预约日期 - 使用北京时间
    from datetime import timezone, timedelta
    beijing_tz = timezone(timedelta(hours=8))
    beijing_now = datetime.now(beijing_tz)
    today = beijing_now.date()
    if order.reservation_date != today:
        return jsonify({'code': 400, 'message': '今日非预约日期，不能签到'}), 400
    
    try:
        order.status = 3  # 已完成
        order.checkin_time = datetime.now()
        db.session.commit()
        
        return jsonify({
            'code': 200,
            'message': '签到成功',
            'data': order.to_dict()
        })
        
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"签到异常: {str(e)}")
        return jsonify({'code': 500, 'message': '服务器错误'}), 500